Micron Document
🎖️GitЯра🎖️

Node / meshcore / MeshCore / files / src / Mesh.h

Displaying Raw • Download

src/Mesh.h 5732b2edd8563281ef7d344cd6517f969ca160ab (5732b2ed) Text, 9.80 KB

Tff7b72#Tff7b72pragma once

Tff7b72#Tff7b72include T8b949e<Dispatcher.h>

Te6edf3namespace Te6edf3mesh Tb4b4b4{

Te6edf3class Te6edf3GroupChannel Tb4b4b4{
Te6edf3publicTff7b72:
Tffa657uint8_t Te6edf3hashTb4b4b4[Te6edf3PATH_HASH_SIZETb4b4b4]Tb4b4b4;
Tffa657uint8_t Te6edf3secretTb4b4b4[Te6edf3PUB_KEY_SIZETb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4;

T8b949e/**
* An abstraction of the data tables needed to be maintained
*/
Te6edf3class Te6edf3MeshTables Tb4b4b4{
Te6edf3publicTff7b72:
Te6edf3virtual Tffa657bool Te6edf3wasSeenTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3virtual Tffa657void Te6edf3markSeenTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3virtual Tffa657void Te6edf3clearTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tff7b72= T79c0ff0Tb4b4b4; T8b949e// remove this packet hash from table
Tb4b4b4}Tb4b4b4;

T8b949e/**
* \brief The next layer in the basic Dispatcher task, Mesh recognises the particular Payload TYPES,
* and provides virtual methods for sub-classes on handling incoming, and also preparing outbound Packets.
*/
Te6edf3class Te6edf3Mesh Tff7b72: Te6edf3public Te6edf3Dispatcher Tb4b4b4{
Te6edf3RTCClockTff7b72* Te6edf3_rtcTb4b4b4;
Te6edf3RNGTff7b72* Te6edf3_rngTb4b4b4;
Te6edf3MeshTablesTff7b72* Te6edf3_tablesTb4b4b4;

Tffa657void Td2a8ffremoveSelfFromPathTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4)Tb4b4b4;
Tffa657void Td2a8ffrouteDirectRecvAcksTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTb4b4b4)Tb4b4b4;
T8b949e//void routeRecvAcks(Packet* packet, uint32_t delay_millis);
Te6edf3DispatcherAction Td2a8ffforwardMultipartDirectTb4b4b4(Te6edf3PacketTff7b72* Te6edf3pktTb4b4b4)Tb4b4b4;

Te6edf3protectedTff7b72:
Te6edf3DispatcherAction Te6edf3onRecvPacketTb4b4b4(Te6edf3PacketTff7b72* Te6edf3pktTb4b4b4) Te6edf3overrideTb4b4b4;

Te6edf3virtual Tffa657uint32_t Te6edf3getCADFailRetryDelayTb4b4b4(Tb4b4b4) Tff7b72const Te6edf3overrideTb4b4b4;

T8b949e/**
* \brief Decide what to do with received packet, ie. discard, forward, or hold
*/
Te6edf3DispatcherAction Td2a8ffrouteRecvPacketTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4)Tb4b4b4;

T8b949e/**
* \brief Called _before_ the packet is dispatched to the on..Recv() methods.
* \returns true, if given packet should NOT be processed.
*/
Te6edf3virtual Tffa657bool Te6edf3filterRecvFloodPacketTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{ Tff7b72return Tffa657falseTb4b4b4; Tb4b4b4}

T8b949e/**
* \brief Check whether this packet should be forwarded (re-transmitted) or not.
* Is sub-classes responsibility to make sure given packet is only transmitted ONCE (by this node)
*/
Te6edf3virtual Tffa657bool Te6edf3allowPacketForwardTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4)Tb4b4b4;

T8b949e/**
* \returns number of milliseconds delay to apply to retransmitting the given packet.
*/
Te6edf3virtual Tffa657uint32_t Te6edf3getRetransmitDelayTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4)Tb4b4b4;

T8b949e/**
* \returns number of milliseconds delay to apply to retransmitting the given packet, for DIRECT mode.
*/
Te6edf3virtual Tffa657uint32_t Te6edf3getDirectRetransmitDelayTb4b4b4(Tff7b72const Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4)Tb4b4b4;

T8b949e/**
* \returns number of extra (Direct) ACK transmissions wanted.
*/
Te6edf3virtual Tffa657uint8_t Te6edf3getExtraAckTransmitCountTb4b4b4(Tb4b4b4) Tff7b72constTb4b4b4;

T8b949e/**
* \brief Perform search of local DB of peers/contacts.
* \returns Number of peers with matching hash
*/
Te6edf3virtual Tffa657int Te6edf3searchPeersByHashTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3hashTb4b4b4)Tb4b4b4;

T8b949e/**
* \brief lookup the ECDH shared-secret between this node and peer by idx (calculate if necessary)
* \param dest_secret destination array to copy the secret (must be PUB_KEY_SIZE bytes)
* \param peer_idx index of peer, [0..n) where n is what searchPeersByHash() returned
*/
Te6edf3virtual Tffa657void Te6edf3getPeerSharedSecretTb4b4b4(Tffa657uint8_tTff7b72* Te6edf3dest_secretTb4b4b4, Tffa657int Te6edf3peer_idxTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A (now decrypted) data packet has been received (by a known peer).
* NOTE: these can be received multiple times (per sender/msg-id), via different routes
* \param type one of: PAYLOAD_TYPE_TXT_MSG, PAYLOAD_TYPE_REQ, PAYLOAD_TYPE_RESPONSE
* \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned
* \param secret the pre-calculated shared-secret (handy for sending response packet)
* \param data decrypted data from payload
*/
Te6edf3virtual Tffa657void Te6edf3onPeerDataRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint8_t Te6edf3typeTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A TRACE packet has been received. (and has reached the end of its given path)
* NOTE: this may have been initiated by another node.
* \param tag a random (unique-ish) tag set by initiator
* \param auth_code a code to authenticate the packet
* \param flags zero for now
* \param path_snrs single byte SNR*4 for each hop in the path
* \param path_hashes hashes of each repeater in the path
* \param path_len length of the path_snrs[] and path_hashes[] arrays
*/
Te6edf3virtual Tffa657void Te6edf3onTraceRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3tagTb4b4b4, Tffa657uint32_t Te6edf3auth_codeTb4b4b4, Tffa657uint8_t Te6edf3flagsTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3path_snrsTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3path_hashesTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A path TO peer (sender_idx) has been received. (also with optional 'extra' data encoded)
* NOTE: these can be received multiple times (per sender), via different routes
* \param sender_idx index of peer, [0..n) where n is what searchPeersByHash() returned
* \param secret the pre-calculated shared-secret (handy for sending response packet)
* \returns true, if path was accepted and that reciprocal path should be sent
*/
Te6edf3virtual Tffa657bool Te6edf3onPeerPathRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657int Te6edf3sender_idxTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3extraTb4b4b4, Tffa657uint8_t Te6edf3extra_lenTb4b4b4) Tb4b4b4{ Tff7b72return Tffa657falseTb4b4b4; Tb4b4b4}

T8b949e/**
* \brief A new incoming Advertisement has been received.
* NOTE: these can be received multiple times (per id/timestamp), via different routes
*/
Te6edf3virtual Tffa657void Te6edf3onAdvertRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tff7b72const Te6edf3IdentityTff7b72& Te6edf3idTb4b4b4, Tffa657uint32_t Te6edf3timestampTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3app_dataTb4b4b4, Tffa657size_t Te6edf3app_data_lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A (now decrypted) data packet has been received.
* NOTE: these can be received multiple times (per sender/contents), via different routes
* \param secret ECDH shared secret
* \param sender public key provided by sender
*/
Te6edf3virtual Tffa657void Te6edf3onAnonDataRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Te6edf3IdentityTff7b72& Te6edf3senderTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A path TO 'sender' has been received. (also with optional 'extra' data encoded)
* NOTE: these can be received multiple times (per sender), via different routes
*/
Te6edf3virtual Tffa657void Te6edf3onPathRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Te6edf3IdentityTff7b72& Te6edf3senderTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3extraTb4b4b4, Tffa657uint8_t Te6edf3extra_lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A control packet has been received.
*/
Te6edf3virtual Tffa657void Te6edf3onControlDataRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A packet with PAYLOAD_TYPE_RAW_CUSTOM has been received.
*/
Te6edf3virtual Tffa657void Te6edf3onRawDataRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief Perform search of local DB of matching GroupChannels.
* \param channels OUT - store matching channels in this array, up to max_matches
* \returns Number of channels with matching hash
*/
Te6edf3virtual Tffa657int Te6edf3searchChannelsByHashTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3hashTb4b4b4, Te6edf3GroupChannel Te6edf3channelsTb4b4b4[Tb4b4b4]Tb4b4b4, Tffa657int Te6edf3max_matchesTb4b4b4)Tb4b4b4;

T8b949e/**
* \brief An encrypted group data packet has been received.
* NOTE: the same payload can be received multiple times, via different routes
* \param type one of: PAYLOAD_TYPE_GRP_TXT, PAYLOAD_TYPE_GRP_DATA
* \param channel the matching GroupChannel
*/
Te6edf3virtual Tffa657void Te6edf3onGroupDataRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint8_t Te6edf3typeTb4b4b4, Tff7b72const Te6edf3GroupChannelTff7b72& Te6edf3channelTb4b4b4, Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4) Tb4b4b4{ Tb4b4b4}

T8b949e/**
* \brief A simple ACK packet has been received.
* NOTE: same ACK can be received multiple times, via different routes
*/
Te6edf3virtual Tffa657void Te6edf3onAckRecvTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3ack_crcTb4b4b4) Tb4b4b4{ Tb4b4b4}

Te6edf3MeshTb4b4b4(Te6edf3RadioTff7b72& Te6edf3radioTb4b4b4, Te6edf3MillisecondClockTff7b72& Te6edf3msTb4b4b4, Te6edf3RNGTff7b72& Te6edf3rngTb4b4b4, Te6edf3RTCClockTff7b72& Te6edf3rtcTb4b4b4, Te6edf3PacketManagerTff7b72& Te6edf3mgrTb4b4b4, Te6edf3MeshTablesTff7b72& Te6edf3tablesTb4b4b4)
Tff7b72: Te6edf3DispatcherTb4b4b4(Te6edf3radioTb4b4b4, Te6edf3msTb4b4b4, Te6edf3mgrTb4b4b4)Tb4b4b4, Te6edf3_rngTb4b4b4(Tff7b72&Te6edf3rngTb4b4b4)Tb4b4b4, Te6edf3_rtcTb4b4b4(Tff7b72&Te6edf3rtcTb4b4b4)Tb4b4b4, Te6edf3_tablesTb4b4b4(Tff7b72&Te6edf3tablesTb4b4b4)
Tb4b4b4{
Tb4b4b4}

Te6edf3MeshTablesTff7b72* Te6edf3getTablesTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{ Tff7b72return Te6edf3_tablesTb4b4b4; Tb4b4b4}

Te6edf3publicTff7b72:
Tffa657void Te6edf3beginTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657void Td2a8ffloopTb4b4b4(Tb4b4b4)Tb4b4b4;

Te6edf3LocalIdentity Te6edf3self_idTb4b4b4;

Te6edf3RNGTff7b72* Td2a8ffgetRNGTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{ Tff7b72return Te6edf3_rngTb4b4b4; Tb4b4b4}
Te6edf3RTCClockTff7b72* Td2a8ffgetRTCClockTb4b4b4(Tb4b4b4) Tff7b72const Tb4b4b4{ Tff7b72return Te6edf3_rtcTb4b4b4; Tb4b4b4}

Te6edf3PacketTff7b72* Td2a8ffcreateAdvertTb4b4b4(Tff7b72const Te6edf3LocalIdentityTff7b72& Te6edf3idTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3app_dataTff7b72=Tffa657NULLTb4b4b4, Tffa657size_t Te6edf3app_data_lenTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateDatagramTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4, Tff7b72const Te6edf3IdentityTff7b72& Te6edf3destTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateAnonDatagramTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4, Tff7b72const Te6edf3LocalIdentityTff7b72& Te6edf3senderTb4b4b4, Tff7b72const Te6edf3IdentityTff7b72& Te6edf3destTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3data_lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateGroupDatagramTb4b4b4(Tffa657uint8_t Te6edf3typeTb4b4b4, Tff7b72const Te6edf3GroupChannelTff7b72& Te6edf3channelTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3data_lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateAckTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3ackTb4b4b4, Tffa657uint8_t Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateAckTb4b4b4(Tffa657uint32_t Te6edf3ack_crcTb4b4b4) Tb4b4b4{ Tff7b72return Te6edf3createAckTb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4) Tff7b72&Te6edf3ack_crcTb4b4b4, T79c0ff4Tb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3PacketTff7b72* Td2a8ffcreateMultiAckTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3ackTb4b4b4, Tffa657uint8_t Te6edf3lenTb4b4b4, Tffa657uint8_t Te6edf3remainingTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateMultiAckTb4b4b4(Tffa657uint32_t Te6edf3ack_crcTb4b4b4, Tffa657uint8_t Te6edf3remainingTb4b4b4) Tb4b4b4{ Tff7b72return Te6edf3createMultiAckTb4b4b4(Tb4b4b4(Tffa657uint8_t Tff7b72*Tb4b4b4)Tff7b72&Te6edf3ack_crcTb4b4b4, T79c0ff4Tb4b4b4, Te6edf3remainingTb4b4b4)Tb4b4b4; Tb4b4b4}
Te6edf3PacketTff7b72* Td2a8ffcreatePathReturnTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dest_hashTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72*Te6edf3extraTb4b4b4, Tffa657size_t Te6edf3extra_lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreatePathReturnTb4b4b4(Tff7b72const Te6edf3IdentityTff7b72& Te6edf3destTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3secretTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint8_t Te6edf3extra_typeTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72*Te6edf3extraTb4b4b4, Tffa657size_t Te6edf3extra_lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateRawDataTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateTraceTb4b4b4(Tffa657uint32_t Te6edf3tagTb4b4b4, Tffa657uint32_t Te6edf3auth_codeTb4b4b4, Tffa657uint8_t Te6edf3flags Tff7b72= T79c0ff0Tb4b4b4)Tb4b4b4;
Te6edf3PacketTff7b72* Td2a8ffcreateControlDataTb4b4b4(Tff7b72const Tffa657uint8_tTff7b72* Te6edf3dataTb4b4b4, Tffa657size_t Te6edf3lenTb4b4b4)Tb4b4b4;

T8b949e/**
* \brief send a locally-generated Packet with flood routing
*/
Tffa657void Td2a8ffsendFloodTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTff7b72=T79c0ff0Tb4b4b4, Tffa657uint8_t Te6edf3path_hash_sizeTff7b72=T79c0ff1Tb4b4b4)Tb4b4b4;

T8b949e/**
* \brief send a locally-generated Packet with flood routing
* \param transport_codes array of 2 codes to attach to packet
*/
Tffa657void Td2a8ffsendFloodTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint16_tTff7b72* Te6edf3transport_codesTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTff7b72=T79c0ff0Tb4b4b4, Tffa657uint8_t Te6edf3path_hash_sizeTff7b72=T79c0ff1Tb4b4b4)Tb4b4b4;

T8b949e/**
* \brief send a locally-generated Packet with Direct routing
*/
Tffa657void Td2a8ffsendDirectTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tff7b72const Tffa657uint8_tTff7b72* Te6edf3pathTb4b4b4, Tffa657uint8_t Te6edf3path_lenTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4;

T8b949e/**
* \brief send a locally-generated Packet to just neighbor nodes (zero hops)
*/
Tffa657void Td2a8ffsendZeroHopTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4;

T8b949e/**
* \brief send a locally-generated Packet to just neighbor nodes (zero hops), with specific transport codes
* \param transport_codes array of 2 codes to attach to packet
*/
Tffa657void Td2a8ffsendZeroHopTb4b4b4(Te6edf3PacketTff7b72* Te6edf3packetTb4b4b4, Tffa657uint16_tTff7b72* Te6edf3transport_codesTb4b4b4, Tffa657uint32_t Te6edf3delay_millisTff7b72=T79c0ff0Tb4b4b4)Tb4b4b4;

Tb4b4b4}Tb4b4b4;

Tb4b4b4}

Served by rngit 1.5.2 - Generated in 0.05s